using System;
using System.Collections.Generic;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Media3D;
using Microsoft.Win32;
using HelixToolkit.Wpf;
using System.IO;

namespace LaplaceMeshDeformer
{
    public partial class MainWindow : Window
    {
        private TriMesh mesh;
        private LaplaceDeformer deformer;
        private Dictionary<int, Point3D> anchorPoints = new Dictionary<int, Point3D>();
        private int selectedVertexIndex = -1;
        private bool isDragging = false;
        private Point3D lastDragPoint;
        private enum OperationMode { View, Select, Move }
        private OperationMode currentMode = OperationMode.View;

        public MainWindow()
        {
            try
            {
                // 初始化组件
                InitializeComponent();
                
                // 确保在访问UI元素前它们已被初始化
                this.Loaded += MainWindow_Loaded;
            }
            catch (Exception ex)
            {
                Console.WriteLine($"MainWindow构造函数错误: {ex.Message}");
                MessageBox.Show($"初始化应用程序时发生错误: {ex.Message}", "错误", MessageBoxButton.OK, MessageBoxImage.Error);
            }
        }

        private void MainWindow_Loaded(object sender, RoutedEventArgs e)
        {
            try
            {
                // 在UI完全加载后执行初始化逻辑
                LogMessage("拉普拉斯网格变形工具已启动");
                UpdateUIState();
                
                // 设置视窗初始状态
                if (viewPort != null)
                {
                    viewPort.ZoomExtents();
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine($"窗口加载事件处理错误: {ex.Message}");
            }
        }

        #region UI Event Handlers

        private void BtnLoadMesh_Click(object sender, RoutedEventArgs e)
        {
            OpenFileDialog openFileDialog = new OpenFileDialog
            {
                Filter = "OBJ文件 (*.obj)|*.obj|所有文件 (*.*)|*.*",
                Title = "选择三角网格文件"
            };

            if (openFileDialog.ShowDialog() == true)
            {
                LoadMesh(openFileDialog.FileName);
            }
        }

        private void BtnAddAnchor_Click(object sender, RoutedEventArgs e)
        {
            if (mesh == null)
            {
                MessageBox.Show("请先加载网格模型！", "提示", MessageBoxButton.OK, MessageBoxImage.Information);
                return;
            }

            if (selectedVertexIndex >= 0)
            {
                // 创建一个输入对话框获取新位置
                AddAnchorWindow addAnchorWindow = new AddAnchorWindow(mesh.GetVertex(selectedVertexIndex).Position);
                if (addAnchorWindow.ShowDialog() == true)
                {
                    Vector3D newPosition = addAnchorWindow.NewPosition;
                    AddAnchorPoint(selectedVertexIndex, newPosition);
                }
            }
            else
            {
                MessageBox.Show("请先选择一个顶点！", "提示", MessageBoxButton.OK, MessageBoxImage.Information);
                rbModeSelect.IsChecked = true;
            }
        }

        private void BtnClearAnchors_Click(object sender, RoutedEventArgs e)
        {
            if (deformer != null)
            {
                deformer.ClearAnchors();
                anchorPoints.Clear();
                UpdateAnchorsVisual();
                LogMessage("已清除所有锚点");
                UpdateAnchorCount();
            }
        }

        private void BtnDeform_Click(object sender, RoutedEventArgs e)
        {
            if (deformer == null || deformer.AnchorCount == 0)
            {
                MessageBox.Show("请先添加至少一个锚点！", "提示", MessageBoxButton.OK, MessageBoxImage.Information);
                return;
            }

            LogMessage("正在执行拉普拉斯变形...");
            bool success = deformer.Deform();

            if (success)
            {
                LogMessage("变形成功完成！");
                UpdateMeshVisual();
            }
            else
            {
                LogMessage("变形失败！请检查锚点设置");
            }
        }

        private void BtnScaleDeform_Click(object sender, RoutedEventArgs e)
        {
            if (mesh == null)
            {
                MessageBox.Show("请先加载网格模型！", "提示", MessageBoxButton.OK, MessageBoxImage.Information);
                return;
            }

            ScaleDeformWindow scaleWindow = new ScaleDeformWindow(mesh.VertexCount - 1);
            if (scaleWindow.ShowDialog() == true)
            {
                int centerIndex = scaleWindow.CenterIndex;
                double radius = scaleWindow.Radius;
                double scaleFactor = scaleWindow.ScaleFactor;

                LogMessage($"正在执行区域缩放变形... 中心点: {centerIndex}, 半径: {radius}, 缩放因子: {scaleFactor}");
                bool success = deformer.ScaleDeform(centerIndex, radius, scaleFactor);

                if (success)
                {
                    LogMessage("区域缩放变形成功完成！");
                    UpdateMeshVisual();
                }
                else
                {
                    LogMessage("区域缩放变形失败！");
                }
            }
        }

        private void BtnSmooth_Click(object sender, RoutedEventArgs e)
        {
            if (mesh == null)
            {
                MessageBox.Show("请先加载网格模型！", "提示", MessageBoxButton.OK, MessageBoxImage.Information);
                return;
            }

            SmoothWindow smoothWindow = new SmoothWindow();
            if (smoothWindow.ShowDialog() == true)
            {
                int iterations = smoothWindow.Iterations;
                double lambda = smoothWindow.Lambda;

                LogMessage($"正在执行平滑处理... 迭代次数: {iterations}, 强度: {lambda}");
                bool success = deformer.Smooth(iterations, lambda);

                if (success)
                {
                    LogMessage("平滑处理成功完成！");
                    UpdateMeshVisual();
                }
                else
                {
                    LogMessage("平滑处理失败！");
                }
            }
        }

        private void ChkCotangentWeight_CheckedChanged(object sender, RoutedEventArgs e)
        {
            if (deformer != null)
            {
                if (chkCotangentWeight.IsChecked == true)
                {
                    deformer.ComputeCotangentLaplacian();
                    LogMessage("已切换到余切权重拉普拉斯矩阵");
                }
                else
                {
                    deformer.ComputeLaplacianMatrix();
                    LogMessage("已切换到均匀权重拉普拉斯矩阵");
                }
                deformer.ComputeDeltaCoordinates();
            }
        }

        private void BtnSaveMesh_Click(object sender, RoutedEventArgs e)
        {
            if (mesh == null)
            {
                MessageBox.Show("没有可保存的网格！", "提示", MessageBoxButton.OK, MessageBoxImage.Information);
                return;
            }

            SaveFileDialog saveFileDialog = new SaveFileDialog
            {
                Filter = "OBJ文件 (*.obj)|*.obj|所有文件 (*.*)|*.*",
                Title = "保存网格模型",
                DefaultExt = "obj"
            };

            if (saveFileDialog.ShowDialog() == true)
            {
                try
                {
                    TriMeshIO.SaveMesh(mesh, saveFileDialog.FileName);
                    LogMessage($"网格已保存到: {saveFileDialog.FileName}");
                }
                catch (Exception ex)
                {
                    LogMessage($"保存网格失败: {ex.Message}");
                    MessageBox.Show($"保存网格失败: {ex.Message}", "错误", MessageBoxButton.OK, MessageBoxImage.Error);
                }
            }
        }

        private void RbMode_Checked(object sender, RoutedEventArgs e)
        {
            if (rbModeView.IsChecked == true)
            {
                currentMode = OperationMode.View;
                LogMessage("已切换到查看模式");
            }
            else if (rbModeSelect.IsChecked == true)
            {
                currentMode = OperationMode.Select;
                LogMessage("已切换到选择锚点模式");
            }
            else if (rbModeMove.IsChecked == true)
            {
                currentMode = OperationMode.Move;
                LogMessage("已切换到移动锚点模式");
            }
        }

        private void ViewPort_MouseDown(object sender, MouseButtonEventArgs e)
        {
            if (mesh == null || currentMode == OperationMode.View)
                return;

            Point position = e.GetPosition(viewPort);
            
            // 使用射线检测与网格的交点
            var hits = new List<HitTestResult>();
            VisualTreeHelper.HitTest(viewPort, null, 
                result => {
                    hits.Add(result);
                    return HitTestResultBehavior.Continue;
                },
                new PointHitTestParameters(position));

            // 查找最近的相交点
            Point3D? hitPoint = null;
            double minDistance = double.MaxValue;

            foreach (var hit in hits)
            {
                if (hit.VisualHit is ModelVisual3D modelVisual)
                {
                    // 获取相交点
                    var rayHit = viewPort.Viewport.UnProject(position);
                    if (rayHit.HasValue)
                    {
                        hitPoint = rayHit.Value;
                        break;
                    }
                }
            }

            if (hitPoint.HasValue)
            {
                if (currentMode == OperationMode.Select)
                {
                    // 找到最近的顶点
                    selectedVertexIndex = FindNearestVertex(hitPoint.Value);
                    UpdateSelectedVertexInfo();
                    LogMessage($"已选择顶点 #{selectedVertexIndex}");
                }
                else if (currentMode == OperationMode.Move && selectedVertexIndex >= 0)
                {
                    // 开始拖动
                    isDragging = true;
                    lastDragPoint = hitPoint.Value;
                }
            }
        }

        private void ViewPort_MouseMove(object sender, MouseEventArgs e)
        {
            if (!isDragging || selectedVertexIndex < 0 || currentMode != OperationMode.Move)
                return;

            Point position = e.GetPosition(viewPort);
            
            // 获取当前点在3D空间中的位置
            var rayHit = viewPort.Viewport.UnProject(position);
            if (!rayHit.HasValue)
                return;
                
            Point3D newPoint = rayHit.Value;
            System.Windows.Media.Media3D.Vector3D wpfDelta = new System.Windows.Media.Media3D.Vector3D(
                newPoint.X - lastDragPoint.X,
                newPoint.Y - lastDragPoint.Y,
                newPoint.Z - lastDragPoint.Z);

            if (anchorPoints.ContainsKey(selectedVertexIndex))
            {
                Point3D currentPos = anchorPoints[selectedVertexIndex];
                Point3D newPos = new Point3D(
                    currentPos.X + wpfDelta.X,
                    currentPos.Y + wpfDelta.Y,
                    currentPos.Z + wpfDelta.Z);
                
                // 更新锚点位置
                Vector3D newPosVec = ToVector3D(newPos);
                deformer.RemoveAnchor(selectedVertexIndex);
                deformer.AddAnchor(selectedVertexIndex, newPosVec);
                anchorPoints[selectedVertexIndex] = newPos;
                
                UpdateAnchorsVisual();
            }

            lastDragPoint = newPoint;
        }

        private void ViewPort_MouseUp(object sender, MouseButtonEventArgs e)
        {
            isDragging = false;
        }

        #endregion

        #region Helper Methods

        private void LoadMesh(string filePath)
        {
            try
            {
                LogMessage($"正在加载网格: {filePath}");
                mesh = TriMeshIO.LoadMesh(filePath);
                
                if (mesh == null)
                {
                    LogMessage("加载网格失败!");
                    return;
                }
                
                LogMessage($"加载成功! 顶点数: {mesh.VertexCount}, 面数: {mesh.FaceCount}");
                
                // 创建Laplace变形器
                deformer = new LaplaceDeformer(mesh);
                
                // 清除现有锚点
                anchorPoints.Clear();
                selectedVertexIndex = -1;
                
                // 更新UI状态
                UpdateUIState();
                
                // 更新3D视图
                UpdateMeshVisual();
                UpdateAnchorsVisual();
            }
            catch (Exception ex)
            {
                LogMessage($"加载网格出错: {ex.Message}");
                MessageBox.Show($"加载网格出错: {ex.Message}", "错误", MessageBoxButton.OK, MessageBoxImage.Error);
            }
        }

        private void UpdateMeshVisual()
        {
            if (mesh == null)
                return;

            try
            {
                // 确保视觉元素已初始化
                if (meshVisual == null || wireframeVisual == null)
                {
                    LogMessage("警告: 网格可视化对象未初始化");
                    return;
                }

                // 在UI线程上执行，确保线程安全
                Dispatcher.Invoke(() =>
                {
                    try
                    {
                        // 限制处理的面数，防止过大的模型导致渲染崩溃
                        int maxFaces = 50000; // 设置一个合理的上限
                        int facesToRender = Math.Min(mesh.FaceCount, maxFaces);
                        
                        if (mesh.FaceCount > maxFaces)
                        {
                            LogMessage($"警告: 模型面数过多 ({mesh.FaceCount})，仅渲染前 {maxFaces} 个面以提高性能");
                        }

                        // 构建网格
                        MeshBuilder meshBuilder = new MeshBuilder(false, false);
                        int faceCount = 0;
                        
                        // 添加三角形面
                        for (int i = 0; i < facesToRender; i++)
                        {
                            TriMesh.Face face = mesh.GetFace(i);
                            if (face != null && face.VertexCount == 3)
                            {
                                try
                                {
                                    int v0 = face.GetVertexIndex(0);
                                    int v1 = face.GetVertexIndex(1);
                                    int v2 = face.GetVertexIndex(2);
                                    
                                    if (v0 >= 0 && v0 < mesh.VertexCount &&
                                        v1 >= 0 && v1 < mesh.VertexCount &&
                                        v2 >= 0 && v2 < mesh.VertexCount)
                                    {
                                        Vector3D p0 = mesh.GetVertex(v0).Position;
                                        Vector3D p1 = mesh.GetVertex(v1).Position;
                                        Vector3D p2 = mesh.GetVertex(v2).Position;
                                        
                                        // 检查点是否有效（不是NaN或Infinity）
                                        if (IsValidVector(p0) && IsValidVector(p1) && IsValidVector(p2))
                                        {
                                            Point3D point0 = ToPoint3D(p0);
                                            Point3D point1 = ToPoint3D(p1);
                                            Point3D point2 = ToPoint3D(p2);
                                            
                                            meshBuilder.AddTriangle(point0, point1, point2);
                                            faceCount++;
                                        }
                                    }
                                }
                                catch (Exception faceEx)
                                {
                                    // 忽略单个面的错误，继续处理其他面
                                    Console.WriteLine($"处理面 {i} 时出错: {faceEx.Message}");
                                }
                            }
                        }

                        LogMessage($"成功构建网格，渲染了 {faceCount} 个面");
                        
                        // 更新网格模型
                        MeshGeometry3D meshGeometry = meshBuilder.ToMesh();
                        meshVisual.Geometry = meshGeometry;
                        
                        // 可选地减少线框复杂度，避免渲染崩溃
                        RenderWireframe(facesToRender);
                        
                        // 调整相机以显示整个模型
                        viewPort.ZoomExtents(500);
                    }
                    catch (Exception ex)
                    {
                        LogMessage($"构建网格时发生错误: {ex.Message}");
                        Console.WriteLine($"构建网格错误: {ex}");
                    }
                });
            }
            catch (Exception ex)
            {
                LogMessage($"更新网格可视化时发生错误: {ex.Message}");
                Console.WriteLine($"更新网格可视化错误: {ex}");
            }
        }

        private void RenderWireframe(int maxFaces)
        {
            try
            {
                // 限制线框复杂度
                const int maxWireframeLines = 10000; // 合理的线框线段上限
                List<Point3D> wireframePoints = new List<Point3D>();
                int lineCount = 0;
                
                for (int i = 0; i < Math.Min(maxFaces, mesh.FaceCount); i++)
                {
                    if (lineCount >= maxWireframeLines) break;
                    
                    TriMesh.Face face = mesh.GetFace(i);
                    if (face != null && face.VertexCount == 3)
                    {
                        try
                        {
                            int v0 = face.GetVertexIndex(0);
                            int v1 = face.GetVertexIndex(1);
                            int v2 = face.GetVertexIndex(2);
                            
                            if (v0 >= 0 && v0 < mesh.VertexCount &&
                                v1 >= 0 && v1 < mesh.VertexCount &&
                                v2 >= 0 && v2 < mesh.VertexCount)
                            {
                                Vector3D p0 = mesh.GetVertex(v0).Position;
                                Vector3D p1 = mesh.GetVertex(v1).Position;
                                Vector3D p2 = mesh.GetVertex(v2).Position;
                                
                                if (IsValidVector(p0) && IsValidVector(p1) && IsValidVector(p2))
                                {
                                    Point3D point0 = ToPoint3D(p0);
                                    Point3D point1 = ToPoint3D(p1);
                                    Point3D point2 = ToPoint3D(p2);
                                    
                                    wireframePoints.Add(point0);
                                    wireframePoints.Add(point1);
                                    lineCount++;
                                    
                                    wireframePoints.Add(point1);
                                    wireframePoints.Add(point2);
                                    lineCount++;
                                    
                                    wireframePoints.Add(point2);
                                    wireframePoints.Add(point0);
                                    lineCount++;
                                }
                            }
                        }
                        catch (Exception ex)
                        {
                            // 忽略单个面的错误
                            Console.WriteLine($"处理线框面 {i} 时出错: {ex.Message}");
                        }
                    }
                }
                
                wireframeVisual.Points = new Point3DCollection(wireframePoints);
                LogMessage($"成功构建线框，渲染了 {lineCount} 条线段");
            }
            catch (Exception ex)
            {
                LogMessage($"构建线框时发生错误: {ex.Message}");
                Console.WriteLine($"构建线框错误: {ex}");
            }
        }

        private bool IsValidVector(Vector3D v)
        {
            return !double.IsNaN(v.X) && !double.IsInfinity(v.X) &&
                   !double.IsNaN(v.Y) && !double.IsInfinity(v.Y) &&
                   !double.IsNaN(v.Z) && !double.IsInfinity(v.Z);
        }

        private void UpdateAnchorsVisual()
        {
            // 确保anchorsVisual已经初始化
            if (anchorsVisual == null)
            {
                LogMessage("警告: 锚点可视化对象未初始化");
                return;
            }

            try
            {
                // 创建一个新的点集合
                Point3DCollection points = new Point3DCollection();
                
                // 添加所有锚点
                foreach (var entry in anchorPoints)
                {
                    points.Add(entry.Value);
                }
                
                // 安全地设置Points属性
                anchorsVisual.Points = points;
            }
            catch (Exception ex)
            {
                LogMessage($"更新锚点可视化时发生错误: {ex.Message}");
            }
        }

        private void UpdateUIState()
        {
            bool hasMesh = mesh != null;
            bool hasDeformer = deformer != null;
            
            btnAddAnchor.IsEnabled = hasMesh;
            btnClearAnchors.IsEnabled = hasDeformer;
            btnDeform.IsEnabled = hasDeformer && deformer.AnchorCount > 0;
            btnScaleDeform.IsEnabled = hasDeformer;
            btnSmooth.IsEnabled = hasDeformer;
            btnSaveMesh.IsEnabled = hasMesh;
            chkCotangentWeight.IsEnabled = hasDeformer;
            
            rbModeView.IsEnabled = hasMesh;
            rbModeSelect.IsEnabled = hasMesh;
            rbModeMove.IsEnabled = hasMesh;
            
            UpdateAnchorCount();
            UpdateSelectedVertexInfo();
        }

        private void UpdateAnchorCount()
        {
            if (deformer != null)
            {
                txtAnchorCount.Text = $"锚点数量: {deformer.AnchorCount}";
            }
            else
            {
                txtAnchorCount.Text = "锚点数量: 0";
            }
        }

        private void UpdateSelectedVertexInfo()
        {
            if (selectedVertexIndex >= 0 && mesh != null)
            {
                Vector3D pos = mesh.GetVertex(selectedVertexIndex).Position;
                txtSelectedVertex.Text = $"选中顶点: {selectedVertexIndex} ({pos.X:F2}, {pos.Y:F2}, {pos.Z:F2})";
            }
            else
            {
                txtSelectedVertex.Text = "选中顶点: 无";
            }
        }

        private int FindNearestVertex(Point3D point)
        {
            if (mesh == null)
                return -1;
            
            double minDistance = double.MaxValue;
            int nearestIndex = -1;
            
            for (int i = 0; i < mesh.VertexCount; i++)
            {
                Vector3D pos = mesh.GetVertex(i).Position;
                Point3D vertexPoint = ToPoint3D(pos);
                
                double distance = (vertexPoint - point).Length;
                if (distance < minDistance)
                {
                    minDistance = distance;
                    nearestIndex = i;
                }
            }
            
            return nearestIndex;
        }

        private void AddAnchorPoint(int vertexIndex, Vector3D targetPosition)
        {
            if (mesh == null || deformer == null || vertexIndex < 0 || vertexIndex >= mesh.VertexCount)
                return;
            
            deformer.AddAnchor(vertexIndex, targetPosition);
            anchorPoints[vertexIndex] = ToPoint3D(targetPosition);
            
            LogMessage($"已添加锚点 #{vertexIndex}，目标位置: ({targetPosition.X:F2}, {targetPosition.Y:F2}, {targetPosition.Z:F2})");
            
            UpdateAnchorsVisual();
            UpdateAnchorCount();
            UpdateUIState();
        }

        private void LogMessage(string message)
        {
            try
            {
                if (txtLog != null)
                {
                    // 在UI线程上执行，确保线程安全
                    Dispatcher.Invoke(() =>
                    {
                        txtLog.AppendText($"[{DateTime.Now:HH:mm:ss}] {message}\n");
                        txtLog.ScrollToEnd();
                    });
                }
                else
                {
                    // 在txtLog不可用时，输出到控制台
                    Console.WriteLine($"[{DateTime.Now:HH:mm:ss}] {message}");
                }
            }
            catch (Exception ex)
            {
                // 在最坏的情况下，至少尝试记录到控制台
                Console.WriteLine($"无法记录消息: {message}");
                Console.WriteLine($"错误原因: {ex.Message}");
            }
        }

        public void LoadMeshFromPath(string filePath)
        {
            try
            {
                if (System.IO.File.Exists(filePath))
                {
                    // 在UI线程上加载网格
                    Dispatcher.Invoke(() => 
                    {
                        try
                        {
                            LoadMesh(filePath);
                        }
                        catch (Exception ex)
                        {
                            LogMessage($"加载网格文件时出错: {ex.Message}");
                            Console.WriteLine($"加载网格文件时出错: {ex.Message}");
                        }
                    });
                }
                else
                {
                    string errorMessage = $"文件不存在: {filePath}";
                    LogMessage(errorMessage);
                    Console.WriteLine(errorMessage);
                    
                    Dispatcher.Invoke(() => 
                    {
                        MessageBox.Show(errorMessage, "错误", MessageBoxButton.OK, MessageBoxImage.Error);
                    });
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine($"LoadMeshFromPath错误: {ex.Message}");
            }
        }

        #endregion

        #region Conversion Methods

        /// <summary>
        /// 将LaplaceMeshDeformer.Vector3D转换为System.Windows.Media.Media3D.Point3D
        /// </summary>
        private Point3D ToPoint3D(Vector3D vector)
        {
            return new Point3D(vector.X, vector.Y, vector.Z);
        }

        /// <summary>
        /// 将System.Windows.Media.Media3D.Point3D转换为LaplaceMeshDeformer.Vector3D
        /// </summary>
        private Vector3D ToVector3D(Point3D point)
        {
            return new Vector3D(point.X, point.Y, point.Z);
        }

        /// <summary>
        /// 将System.Windows.Media.Media3D.Vector3D转换为LaplaceMeshDeformer.Vector3D
        /// </summary>
        private Vector3D ToVector3D(System.Windows.Media.Media3D.Vector3D vector)
        {
            return new Vector3D(vector.X, vector.Y, vector.Z);
        }

        #endregion
    }
} 